package com.ycxy.sh.transaction.service.impl;

import com.ycxy.sh.transaction.dao.entity.Login;
import com.ycxy.sh.transaction.dao.entity.UserInfo;
import com.ycxy.sh.transaction.dao.entity.UserRole;
import com.ycxy.sh.transaction.dao.vo.LoginListVo;
import com.ycxy.sh.transaction.ex.ServiceException;
import com.ycxy.sh.transaction.mapper.LoginMapper;
import com.ycxy.sh.transaction.mapper.UserInfoMapper;
import com.ycxy.sh.transaction.service.LoginService;
import com.ycxy.sh.transaction.service.UserRoleService;
import com.ycxy.sh.transaction.util.*;
import com.ycxy.sh.transaction.web.JsonResult;
import com.ycxy.sh.transaction.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 *  服务类
 *
 * @author hlt
 * @since 2019-12-21
 */
@Slf4j
@Service
@Transactional
public class LoginServiceImpl implements LoginService {

    @Autowired
    private LoginMapper loginMapper;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private UserInfoMapper userInfoMapper;

    /**手机号和注册验证码map集合*/
    private static Map<String, String> phonecodemap1 = new HashMap<>();
    /**手机号和重置密码验证码map集合*/
    private static Map<String, String> phonecodemap2 = new HashMap<>();

    @Override
    public void sendCode(int type,String mobilePhone,HttpServletRequest request) {
        log.debug("开始处理发送验证码业务...");
        Login login = new Login();
        if(type!=0){
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"违规操作");
        }
        if (!JustPhone.justPhone(mobilePhone)) {//判断输入的手机号格式是否正确
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"请输入正确格式的手机号");
        }
        //查询手机号是否已经注册
        login.setMobilePhone(mobilePhone);
        Login userIsExist = loginMapper.userLogin(login);
        if (!StringUtils.isEmpty(userIsExist)){//用户账号已经存在
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"手机号已存在");
        }
        String code = GetCode.phonecode();
        Integer result = new SmsUtil().SendMsg(mobilePhone, code, type);//发送验证码
        if(result == 1){//发送成功
            phonecodemap1.put(mobilePhone, code);//放入map集合进行对比
             log.debug("验证码发送成功");
        }else if(result == 2){
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"请输入正确格式的手机号");
        }else{
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"验证码发送失败");
        }
    }

    /**
     * 管理员登录
     * @param login
     * @param session
     */
    @Override
    public void login(Login login, HttpSession session) {
        String loginusername=login.getUsername();
        String password=login.getPassword();
        String verCode=login.getVercode();
        UsernamePasswordToken token;
        if(!ValidateCode.code.equalsIgnoreCase(verCode)){
            String message="验证码错误";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_UNAUTHORIZED,message);
        }
        //判断输入的账号是否手机号
        if (!JustPhone.justPhone(loginusername)) {
            //输入的是用户名
            String username = loginusername;
            //盐加密
            token=new UsernamePasswordToken(username, new Md5Hash(password,"Secondhand-shops").toString());
        }else {
            //输入的是手机号
            String mobilephone = loginusername;
            login.setMobilePhone(mobilephone);
            //将封装的login中username变为null
            login.setUsername(null);
            //盐加密
            token=new UsernamePasswordToken(mobilephone, new Md5Hash(password,"Secondhand-shops").toString());
        }
        Subject subject= SecurityUtils.getSubject();
        try {
            subject.login(token);
            //盐加密
            String passwords = new Md5Hash(password, "Secondhand-shops").toString();
            login.setPassword(passwords);
            Login login1 = loginMapper.userLogin(login);
            //查询登录者的权限
            Long roleId = Long.valueOf(userRoleService.LookUserRoleId(login1.getUserId()));
            if (roleId == 2 || roleId == 3){
                session.setAttribute("admin",login1.getUsername());
                session.setAttribute("username",login1.getUsername());
                String message="登录成功";
                log.debug(message);
                throw  new ServiceException(ServiceCode.OK,message);
            }throw  new ServiceException(ServiceCode.ERR_FORBIDDEN,"权限不足");
        }catch (UnknownAccountException e){
            throw  new ServiceException(ServiceCode.ERR_NOT_FOUND,"用户名不存在");
        }catch (IncorrectCredentialsException e){
            throw  new ServiceException(ServiceCode.ERR_NOT_FOUND,"密码错误");
        }
    }

    /**
     * 用户登录
     */
    @Override
    public void userStaredLogin(Login login, HttpSession session) {
        log.debug("开始处理网络用户登录业务...");
        String account=login.getUsername();
        String password=login.getPassword();
        String verCode=login.getVercode();
        UsernamePasswordToken token;
        if(!ValidateCode.code.equalsIgnoreCase(verCode)){
            throw  new ServiceException(ServiceCode.ERR_NOT_FOUND,"请输入正确的验证码");
        }
        //判断输入的账号是否手机号
        if (!JustPhone.justPhone(account)) {
            //输入的是用户名
            String username = account;
            //盐加密
            token=new UsernamePasswordToken(username, new Md5Hash(password,"Campus-shops").toString());
        }else {
            //输入的是手机号
            String mobilephone = account;
            login.setMobilePhone(mobilephone);
            //将封装的login中username变为null
            login.setUsername(null);
            //盐加密
            token=new UsernamePasswordToken(mobilephone, new Md5Hash(password,"Campus-shops").toString());
        }
        Subject subject= SecurityUtils.getSubject();
        try {
            subject.login(token);
            //盐加密
            String passwords = new Md5Hash(password, "Campus-shops").toString();
            login.setPassword(passwords);
            Login login1 = loginMapper.userLogin(login);
            session.setAttribute("userid",login1.getUserId());
            session.setAttribute("username",login1.getUsername());
            log.debug("用户登录成功");
        }catch (UnknownAccountException e){
            throw  new ServiceException(ServiceCode.ERR_NOT_FOUND,"用户名不存在");
        }catch (IncorrectCredentialsException e){
            throw  new ServiceException(ServiceCode.ERR_NOT_FOUND,"密码错误");
        }
    }

    /**
     * 查询用户列表数据
     * @return
     */
    @Override
    public List<LoginListVo> list() {
        log.debug("正在查询登录用户列表");
        List<LoginListVo> list = loginMapper.list();
        //处理隐藏系统管理员
        Iterator<LoginListVo> iterator = list.iterator();
        while (iterator.hasNext()){
            if(iterator.next().getRoleId()==3){
                iterator.remove();
                break;
            }
        }
        return list;
    }

    /**
     * 注册
     * @param userInfo
     * @param session
     * @return
     */
    public Integer loginRegister(UserInfo userInfo,HttpSession session){
        String username = userInfo.getUsername();
        String password = userInfo.getPassword();
        String mobilePhone = userInfo.getMobilePhone();
        String verCode = userInfo.getVerCode();
        Login login = new Login().setMobilePhone(mobilePhone);
        //查询账号(手机号)是否已经注册
        Login userIsExist = loginMapper.userLogin(login);
        if (!StringUtils.isEmpty(userIsExist)){//用户账号已经存在
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,"该用户已经注册过了");
        }
        login.setUsername(username).setMobilePhone(null);
        Login userNameIsExist = loginMapper.userLogin(login);
        if (!StringUtils.isEmpty(userNameIsExist)){//用户名已经存在
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,"该用户名已存在,请重新输入");
        }
        String rel = phonecodemap1.get(mobilePhone);
        if (StringUtils.isEmpty(rel)) {//验证码到期 或者 没发送短信验证码
            throw  new ServiceException(ServiceCode.ERR_NOT_FOUND,"请重新获取验证码");
        }
        if (rel.equalsIgnoreCase(verCode)) {//验证码正确
            //盐加密
            String passwords = new Md5Hash(password, "Secondhand-shops").toString();
            Long userid = Long.valueOf(KeyUtil.genUniqueKey());
            login.setId(Long.valueOf(KeyUtil.genUniqueKey())).setUserId(userid).setMobilePhone(mobilePhone).setPassword(passwords);
            Integer integer = loginMapper.loginAdd(login);
            //新注册用户存入默认头像、存入默认签名
            userInfo.setUserId(userid).setPassword(passwords).setUserImage("/pic/d1d66c3ea71044a9b938b00859ca94df.jpg").
                    setSign("过去终究是过去,过去的遗憾不能填补").setStatus("offline");
            //添加用户信息
            int integer1 = userInfoMapper.insert(userInfo);
            if (integer < 1 || integer1 < 1){
                throw  new ServiceException(ServiceCode.ERR_NOT_FOUND,"注册失败");
            }else{
                /**注册成功后存入session*/
                session.setAttribute("userid",userid);
                session.setAttribute("username",username);
                /**存入用户角色信息*/
                userRoleService.InsertUserRole(new UserRole().setUserId(userid).setRoleId(1).setIdentity("网站用户"));
                UsernamePasswordToken token=new UsernamePasswordToken(mobilePhone, new Md5Hash(password,"Campus-shops").toString());
                Subject subject= SecurityUtils.getSubject();
                subject.login(token);
                log.debug("注册成功");
            }
        }
        throw  new ServiceException(ServiceCode.ERR_NOT_FOUND,"验证码错误,请重新输入");
    }

    /**
     * 重置密码时发送验证码
     * @param type
     * @param mobilePhone
     * @param request
     */
    @Override
    public void sendResetPassword(int type, String mobilePhone, HttpServletRequest request) {
        log.debug("开始处理发送验证码业务...");
        Login login = new Login();
        if(type!=1){
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"违规操作");
        }
        if (!JustPhone.justPhone(mobilePhone)) {//判断输入的手机号格式是否正确
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"请输入正确格式的手机号");
        }
        //查询手机号是否已经注册
        login.setMobilePhone(mobilePhone);
        Login userIsExist = loginMapper.userLogin(login);
        if (!StringUtils.isEmpty(userIsExist)){//用户账号已经存在
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"手机号已存在");
        }
        String code = GetCode.phonecode();
       //Integer result = new SmsUtil().SendMsg(mobilePhone, code, type);//发送验证码
        //默认发送验证码
        Integer result = ValidateCodeUtils.generateValidateCode(4);
        log.info("code={}",result);
        if(result == 1){//发送成功
            phonecodemap2.put(mobilePhone, code);//放入map集合进行对比
            log.debug("验证码发送成功");
        }else if(result == 2){
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"请输入正确格式的手机号");
        }else{
            throw new ServiceException(ServiceCode.ERR_FORBIDDEN,"验证码发送失败");
        }
    }
    /**
     * 重置密码
     * @param login
     */
    @Override
    public void resetPassword(Login login) {
        String mobilephone=login.getMobilePhone();
        String password=login.getPassword();
        String vercode=login.getVercode();
        Login login1 = new Login();
        UserInfo userInfo = new UserInfo();
        if (!JustPhone.justPhone(mobilephone)) {//判断输入的手机号格式是否正确
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"请输入正确格式的手机号");
        }
        //查询手机号是否存在
        login1.setMobilePhone(mobilephone);
        Login userIsExist = loginMapper.userLogin(login1);
        if (StringUtils.isEmpty(userIsExist)){//用户账号不存在
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"该账号不存在");
        }
        String rcode = phonecodemap2.get(mobilephone);
        if (StringUtils.isEmpty(rcode)) {//验证码到期 或者 没发送短信验证码
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"验证码已过期,请重新获取验证码");
        }
        if (rcode.equalsIgnoreCase(vercode)) {//验证码正确
            //盐加密
            String passwords = new Md5Hash(password, "Secondhand-shops").toString();
            login1.setPassword(passwords).setId(userIsExist.getId()).setMobilePhone(null);
            userInfo.setMobilePhone(mobilephone).setPassword(passwords).setUserId(userIsExist.getUserId());
            Integer integer = loginMapper.updateLogin(login1);
            Integer integer1 = userInfoMapper.Update(userInfo);
            if (integer<1 || integer1<1){
                String message="重置密码失败";
                log.debug(message);
                throw new ServiceException(ServiceCode.ERR_UPDATE,message);
            }
        }
        throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"验证码错误");
    }

}
